home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i049: NN Newsreader, release 6.4, Part14/21
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: a99df884 bc7915d1 6daa6fb5 f771e8c9
-
- Submitted-by: "Kim F. Storm" <storm@texas.dk>
- Posting-number: Volume 22, Issue 49
- Archive-name: nn6.4/part14
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: answer.c conf/s-aix221.h macro.c nn.c
- # Wrapped by storm@texas.dk on Sun May 6 18:19:57 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 14 (of 22)."'
- if test -f 'answer.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'answer.c'\"
- else
- echo shar: Extracting \"'answer.c'\" \(18768 characters\)
- sed "s/^X//" >'answer.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- X *
- X * Response handling.
- X */
- X
- X#include "config.h"
- X#include "news.h"
- X#include "term.h"
- X#include "keymap.h"
- X#include "options.h"
- X
- Xextern char *temp_file;
- X
- Xexport char *default_distribution = NULL;
- Xexport char *extra_mail_headers = NULL;
- Xexport char *extra_news_headers = NULL;
- Xexport char *mail_record = NULL;
- Xexport char *news_record = NULL;
- Xexport char *mail_script = NULL;
- Xexport char *news_script = NULL;
- Xexport char *mailer_program = REC_MAIL;
- Xexport int mailer_pipe_input = 1;
- Xexport char *editor_program = NULL;
- Xexport char *spell_checker = NULL;
- X
- Xexport char *bug_address = BUG_REPORT_ADDRESS;
- X
- Xexport int include_art_id = 0;
- Xexport int include_full_header = 0;
- Xexport int orig_to_include_mask = 0x3;
- X
- Xexport int empty_answer_check = 1; /* reject replies that are not edited */
- Xexport int response_check_pause = 0; /* time to wait for background cmds */
- Xexport char *response_dflt_answer = "send";
- X
- X#ifdef APPEND_SIGNATURE
- Xexport int append_sig_mail = 1; /* mail does not append it */
- X#else
- Xexport int append_sig_mail = 0;
- X#endif
- Xexport int append_sig_post = 0; /* inews should always do this */
- Xexport int query_signature = 1; /* query user */
- X
- X
- X#define INCL_MARK_SIZE 10
- X
- Xexport char included_mark[INCL_MARK_SIZE + 1] = ">";
- X
- Ximport char delayed_msg[];
- X
- Xstatic int ed_line;
- X
- X#ifdef NNTP
- X#ifdef NNTP_MINI_INEWS_HEADER
- X#include <time.h>
- X
- Xstatic mini_inews_header(t)
- XFILE *t;
- X{
- X time_t now;
- X extern struct tm *gmtime();
- X extern char *asctime();
- X char *date, host[64];
- X
- X now = cur_time();
- X date = asctime(gmtime(&now));
- X date[3] = date[7] = date[10] = date[19] = date[24] = NUL;
- X gethostname(host, 64);
- X
- X fprintf(t, "Path: %s!%s\n", host, user_name());
- X fprintf(t, "Date: %s %s %s %s GMT\n", date+8, date+4, date+22, date+11);
- X fprintf(t, "Message-ID: <%s.%ld@%s>\n", user_name, (long)now, host);
- X ed_line += 3;
- X}
- X#endif
- X#endif
- X
- Xstatic subj_line(t, re, subj, prefix)
- XFILE *t;
- Xint re;
- Xchar *subj, *prefix;
- X{
- X if (subj == NULL) return 0;
- X
- X fputs("Subject: ", t);
- X
- X if (re >= 0)
- X fputs("Re: ", t);
- X
- X if (prefix) {
- X fputs(prefix, t);
- X fputc(' ', t);
- X }
- X
- X fputs(subj, t);
- X fputc(NL, t);
- X
- X ed_line++;
- X return 1;
- X}
- X
- X
- Xstatic ng_line(t, use_follow)
- XFILE *t;
- Xint use_follow;
- X{
- X fprintf(t, "Newsgroups: %s\n",
- X use_follow && news.ng_follow ? news.ng_follow : news.ng_groups);
- X ed_line++;
- X}
- X
- Xstatic ref_line(t)
- XFILE *t;
- X{
- X if (news.ng_ref == NULL && news.ng_ident == NULL) return;
- X
- X fputs("References:", t);
- X if (news.ng_ref) fprintf(t, " %s", news.ng_ref);
- X if (news.ng_ident) fprintf(t, " %s", news.ng_ident);
- X putc(NL, t);
- X ed_line++;
- X}
- X
- X
- Xstatic to_line(t, to)
- XFILE *t;
- Xchar *to;
- X{
- X if (to == NULL) return 0;
- X
- X fprintf(t, "To: %s\n", to);
- X ed_line++;
- X return 1;
- X}
- X
- Xstatic alt_to_line(t, to, mask)
- XFILE *t;
- Xchar *to;
- Xint mask;
- X{
- X if (to == NULL) return;
- X if (mask && (orig_to_include_mask & mask) == 0) return;
- X
- X fprintf(t, "Orig-To: %s\n", to);
- X ed_line++;
- X}
- X
- Xstatic end_header(t, extra_headers)
- XFILE *t;
- Xregister char *extra_headers;
- X{
- X if (extra_headers != NULL && *extra_headers != NUL) {
- X while (*extra_headers != NUL) {
- X if (*extra_headers == ';') {
- X if (*++extra_headers == NUL) break;
- X fputc(NL, t);
- X ed_line++;
- X } else
- X fputc(*extra_headers++, t);
- X }
- X fputc(NL, t);
- X ed_line++;
- X }
- X
- X fputc(NL, t);
- X ed_line++;
- X}
- X
- X
- Xstatic reply_to(t, address)
- XFILE *t;
- Xchar *address;
- X{
- X char route[512];
- X
- X if (address == NULL) return 0;
- X
- X if (reroute(route, address)) {
- X to_line(t, route);
- X return 1;
- X }
- X return 0;
- X}
- X
- X
- X/*
- X * invoke aux shell script with suitable arguments
- X *
- X * WARNING: record may be NULL, so it must be the last argument!!
- X */
- X
- Xstatic aux_param_bool(f, name, on)
- XFILE *f;
- Xchar *name;
- Xint on;
- X{
- X fprintf(f, "%s=%s\n", name, on ? "true" : "false");
- X}
- X
- Xstatic aux_param_str(f, name, str)
- XFILE *f;
- Xchar *name, *str;
- X{
- X fprintf(f, "%s='%s'\n", name, str != NULL ? str : "");
- X}
- X
- Xstatic aux_param_int(f, name, i)
- XFILE *f;
- Xchar *name;
- Xint i;
- X{
- X fprintf(f, "%s=%d\n", name, i);
- X}
- X
- Xstatic aux_sh(ah, script, prog, action, record, sent_fmt, append_sig)
- Xarticle_header *ah;
- Xchar *script, *prog, *action, *record, *sent_fmt;
- Xint append_sig;
- X{
- X FILE *param;
- X char *args[10], *fn;
- X register char **ap = args;
- X import int novice;
- X import char *pager;
- X#ifdef NNTP
- X extern char *nntp_get_filename();
- X#endif
- X
- X param = open_file(relative(nn_directory, ".param"), OPEN_CREATE);
- X if (param == NULL) {
- X strcpy(delayed_msg, "cannot create .param file for aux script");
- X return 0;
- X }
- X
- X if (strcmp(prog, "cancel") == 0) {
- X aux_param_str(param, "ART_ID", action); /* article id for cancel */
- X aux_param_str(param, "GROUP", record); /* group name for cancel */
- X } else {
- X aux_param_str(param, "FIRST_ACTION", action);
- X aux_param_str(param, "RECORD", record);
- X aux_param_str(param, "WORK", temp_file);
- X aux_param_int(param, "ED_LINE", ed_line);
- X
- X aux_param_bool(param, "NOVICE", novice);
- X aux_param_bool(param, "EMPTY_CHECK", empty_answer_check);
- X aux_param_bool(param, "APPEND_SIG", append_sig);
- X aux_param_bool(param, "QUERY_SIG", append_sig && query_signature);
- X
- X if (editor_program != NULL)
- X aux_param_str(param, "EDITOR", editor_program);
- X aux_param_str(param, "SPELL_CHECKER", spell_checker);
- X aux_param_str(param, "PAGER", pager);
- X aux_param_str(param, "MAILER", mailer_program);
- X aux_param_bool(param, "MAILER_PIPE", mailer_pipe_input);
- X aux_param_int(param, "WAIT_PERIOD", response_check_pause);
- X aux_param_str(param, "DFLT_ANSW", response_dflt_answer);
- X
- X if (current_group != NULL) {
- X aux_param_str(param, "G", current_group->group_name);
- X if (ah == NULL)
- X fn = NULL;
- X else
- X#ifdef NNTP
- X if (use_nntp)
- X fn = nntp_get_filename(ah->a_number, current_group);
- X else
- X#endif
- X fn = group_path_name;
- X aux_param_str(param, "A", fn != NULL ? fn : "");
- X }
- X
- X /*
- X aux_param_str(param, "", );
- X aux_param_bool(param, "", );
- X aux_param_int(param, "", );
- X */
- X }
- X
- X fclose(param);
- X
- X stop_usage();
- X
- X /* OBS: relative() returns ptr to static data below */
- X *ap++ = "nnaux";
- X *ap++ = script != NULL ? script : relative(lib_directory, "aux");
- X *ap++ = prog;
- X *ap++ = NULL;
- X
- X if (execute(SHELL, args, 1)) {
- X sprintf(delayed_msg, sent_fmt, " not");
- X return 1;
- X }
- X sprintf(delayed_msg, sent_fmt, "");
- X return 0;
- X}
- X
- Xstatic append_file(name, f)
- Xchar *name;
- Xregister FILE *f;
- X{
- X register FILE *s;
- X register int c;
- X
- X s = open_file(name, OPEN_READ);
- X if (s == NULL) return;
- X
- X while ((c = getc(s)) != EOF) putc(c, f);
- X fclose(s);
- X}
- X
- Xanswer(ah, command, incl)
- Xarticle_header *ah;
- Xint command;
- Xint incl; /* <0: ask, 0: don't include, >0: include article */
- X{
- X register FILE *t, *art;
- X char *pgm, *first_action, *record_file;
- X int edit_message, append_sig;
- X char *str, *script;
- X news_header_buffer nhbuf, dhbuf;
- X
- X first_action = "edit";
- X edit_message = 1;
- X append_sig = 0;
- X
- X if (incl < 0) {
- X prompt("Include original article? ");
- X if ((incl = yes(0)) < 0) return 0;
- X }
- X
- X art = NULL;
- X if (ah && ah->a_group) init_group(ah->a_group);
- X
- X if (incl || (command != K_MAIL_OR_FORWARD && command != K_BUG_REPORT)) {
- X int open_modes;
- X
- X open_modes = FILL_NEWS_HEADER | GET_ALL_FIELDS | SKIP_HEADER;
- X if (ah->flag & A_DIGEST) open_modes |= FILL_DIGEST_HEADER;
- X
- X art = open_news_article(ah, open_modes, nhbuf, dhbuf);
- X if (art == NULL) {
- X msg("Can't find original article");
- X return 0;
- X }
- X
- X if (ah->flag & A_DIGEST) {
- X if (digest.dg_from)
- X news.ng_path = news.ng_from = digest.dg_from;
- X if (digest.dg_subj)
- X news.ng_subj = digest.dg_subj;
- X }
- X } else
- X ah = NULL;
- X
- X /* build header */
- X new_temp_file();
- X
- X if ((t = open_file(temp_file, OPEN_CREATE)) == NULL) {
- X msg("Can't create %s", temp_file);
- X return 0;
- X }
- X
- X ed_line = 0;
- X
- X follow_to_poster:
- X
- X record_file = mail_record;
- X script = mail_script;
- X
- X if (command == K_REPLY) {
- X pgm = "reply";
- X append_sig = append_sig_mail;
- X
- X ah->flag |= A_ST_REPLY;
- X
- X if (reply_to(t, news.ng_reply) ||
- X reply_to(t, news.ng_from) ||
- X reply_to(t, news.ng_path)) goto alt0;
- X if (to_line(t, news.ng_reply)) goto alt1;
- X if (to_line(t, news.ng_from)) goto alt2;
- X if (to_line(t, news.ng_path)) goto alt3;
- X goto err;
- X
- X alt0:
- X alt_to_line(t, news.ng_reply, 0x1);
- X alt1:
- X alt_to_line(t, news.ng_from, 0x2);
- X alt2:
- X alt_to_line(t, news.ng_path, 0x4);
- X alt3:
- X
- X if (news.ng_subj)
- X subj_line(t, ah->replies, ah->subject, (char *)NULL);
- X else
- X subj_line(t, 0, current_group->group_name, "Your Article in");
- X
- X ng_line(t, 0);
- X ref_line(t);
- X
- X end_header(t, extra_mail_headers);
- X
- X if (incl) {
- X fprintf(t, "In %s you write:\n", current_group->group_name);
- X ed_line++;
- X }
- X }
- X
- X if (command == K_FOLLOW_UP) {
- X if (news.ng_follow && strcmp(news.ng_follow, "poster") == 0) {
- X command = K_REPLY;
- X msg("Followup by reply to poster");
- X goto follow_to_poster;
- X }
- X
- X pgm = "follow";
- X record_file = news_record;
- X script = news_script;
- X append_sig = append_sig_post;
- X
- X ah->flag |= A_ST_FOLLOW;
- X
- X#ifdef NNTP
- X#ifdef NNTP_MINI_INEWS_HEADER
- X mini_inews_header(t);
- X#endif
- X#endif
- X ng_line(t, 1);
- X
- X if (news.ng_subj)
- X subj_line(t, ah->replies, ah->subject, (char *)NULL);
- X else
- X if (!subj_line(t, 0, news.ng_from, "Babble from"))
- X if (!subj_line(t, 0, news.ng_ident, "Article")) {
- X prompt("Subject: ");
- X str = get_s(NONE, NONE, NONE, NULL_FCT);
- X if (str == NULL) goto err;
- X subj_line(t, -1, str, (char *)NULL);
- X }
- X
- X if (news.ng_keyw) {
- X fprintf(t, "Keywords: %s\n", news.ng_keyw);
- X ed_line++;
- X }
- X
- X if (news.ng_dist) {
- X fprintf(t, "Distribution: %s\n", news.ng_dist);
- X ed_line++;
- X }
- X
- X ref_line(t);
- X
- X end_header(t, extra_news_headers);
- X
- X if (incl) {
- X if (news.ng_from) {
- X if (include_art_id && news.ng_ident)
- X fprintf(t, "In%s %s ",
- X ah->flag & A_DIGEST ? " digest" : "",
- X news.ng_ident);
- X fprintf(t, "%s writes:\n", news.ng_from);
- X ed_line++;
- X } else
- X if (news.ng_ident) {
- X fprintf(t, "In %s %s:\n",
- X ah->flag & A_DIGEST ? "digest" : "article",
- X news.ng_ident);
- X ed_line++;
- X }
- X }
- X }
- X
- X if (command == K_MAIL_OR_FORWARD || command == K_BUG_REPORT) {
- X pgm = incl ? "forward" : "mail";
- X append_sig = append_sig_mail;
- X
- X m3_again:
- X prompt("To: ");
- X str = get_s(user_name(),
- X command == K_BUG_REPORT ? bug_address : NONE,
- X NONE, NULL_FCT);
- X if (str == NULL) goto close_t;
- X
- X if (*str == NUL) str = user_name();
- X if (*str == '?') goto m3_again;
- X
- X if (strcmp(str, user_name()) == 0)
- X record_file = NULL; /* we will get this anyway,
- X there is so no need to save it */
- X
- X/* if (reply_to(t, str)) { alt_to_line(t, str, 0); } else */
- X to_line(t, str);
- X
- X do {
- X prompt("Subject: ");
- X str = get_s(incl ? ah->subject : NONE,
- X command == K_BUG_REPORT ? "nn bug report" : NONE,
- X NONE, NULL_FCT);
- X if (str == NULL) goto close_t;
- X if (*str == NUL && incl) str = ah->subject;
- X } while (*str == NUL);
- X
- X subj_line(t, -1, str, (char *)NULL);
- X
- X end_header(t, extra_mail_headers);
- X
- X if (incl) {
- X prompt("\1Edit\1 forwarded message? ");
- X if ((edit_message = yes(0)) < 0) goto close_t;
- X if (!edit_message) {
- X first_action = "send";
- X fseek(art, ah->hpos, 0);
- X } else
- X if (include_full_header && command == K_MAIL_OR_FORWARD)
- X fseek(art, ah->hpos, 0);
- X }
- X
- X if (command == K_BUG_REPORT) {
- X fprintf(t, "\n=== configuration ===\n");
- X append_file(relative(lib_directory, "conf"), t);
- X fprintf(t, "=== end ===\n");
- X }
- X }
- X
- X /* empty line terminates header */
- X fputc(NL, t);
- X ed_line++;
- X
- X prompt("\1WAIT\1");
- X
- X if (incl) {
- X register c, prevnl = 1;
- X
- X while ((c = getc(art)) != EOF) {
- X if (c == NL) {
- X putc(c, t);
- X if (ftell(art) >= ah->lpos) break;
- X prevnl++;
- X continue;
- X }
- X if (prevnl) {
- X if (command != K_MAIL_OR_FORWARD || ftell(art) < ah->fpos)
- X fputs(included_mark, t);
- X prevnl = 0;
- X }
- X putc(c, t);
- X }
- X } else {
- X putc(NL, t);
- X ed_line++;
- X }
- X
- X fclose(t);
- X if (art) fclose(art);
- X
- X aux_sh(ah, script, pgm, first_action, record_file,
- X command == K_FOLLOW_UP ? "Article%s posted" : "Mail%s sent",
- X append_sig);
- X
- X return edit_message;
- X
- X err:
- X msg("Can't build header for %s",
- X command != K_FOLLOW_UP ? "letter" : "article");
- X
- X close_t:
- X fclose(t);
- X unlink(temp_file);
- X if (art) fclose(art);
- X
- X return 0;
- X}
- X
- X
- X/*
- X * inet_name: return "<user_name()>@<host_name()>"
- X */
- X
- Xstatic char *inet_name()
- X{
- X static char *inetname = NULL;
- X char hname[100], *un;
- X
- X if (inetname == NULL) {
- X gethostname(hname, 100);
- X un = user_name();
- X inetname = newstr(strlen(hname) + strlen(un) + 2);
- X sprintf(inetname, "%s@%s", un, hname);
- X }
- X return inetname;
- X}
- X
- X/*
- X * check_sender: If sender is "root", "news", the full name or the internet
- X * name of the user, return 1 otherwise 0
- X */
- X
- Xstatic int check_sender(sender)
- Xchar *sender;
- X{
- X char *full_name();
- X
- X return strcmp(user_name(), "root") == 0
- X || strcmp(user_name(), "news") == 0
- X || strmatch(full_name(), sender)
- X || strmatch(inet_name(), sender);
- X}
- X
- X
- Xcancel(ah)
- Xarticle_header *ah;
- X{
- X news_header_buffer nhbuf;
- X FILE *f;
- X
- X if (ah->a_group) init_group(ah->a_group);
- X
- X if (ah->flag & A_DIGEST) {
- X fputs("\rCancel entire digest ? ", stdout); clrline();
- X if (yes(1) > 0)
- X ah->flag &= ~A_DIGEST;
- X else {
- X msg("Can only cancel entire digests (yet?)");
- X return 2;
- X }
- X }
- X
- X f = open_news_article(ah, FILL_NEWS_HEADER|GET_ALL_FIELDS, nhbuf, (char *)NULL);
- X if (f == NULL) {
- X msg("Article not found");
- X return 2;
- X }
- X fclose(f);
- X
- X if (! check_sender(news.ng_from)) {
- X msg("You can only cancel your own articles!");
- X return 1;
- X }
- X
- X prompt("Confirm cancel: '%s: %.30s'",
- X ah->sender ? ah->sender : "",
- X ah->subject ? ah->subject : "");
- X if (yes(1) <= 0) return 1;
- X
- X printf("\rCancelling article %s in group %s",
- X news.ng_ident, current_group->group_name);
- X clrline();
- X
- X ed_line = -1;
- X
- X if (aux_sh(ah, (char *)NULL, "cancel", news.ng_ident, current_group->group_name,
- X "Article%s cancelled", 0))
- X return -1;
- X
- X return 0;
- X}
- X
- Xstatic char *post_distribution = NULL;
- Xstatic char *post_subject = NULL;
- Xstatic char *post_summary = NULL;
- Xstatic char *post_keywords = NULL;
- Xstatic char *post_source_file = NULL;
- Xstatic int post_no_edit = 0;
- Xstatic char *post_to_groups = NULL;
- X
- XOption_Description(post_options) {
- X 'd', String_Option(post_distribution),
- X 'f', String_Option(post_source_file),
- X 'k', String_Option(post_keywords),
- X 's', String_Option(post_subject),
- X 'y', String_Option(post_summary),
- X 'p', Bool_Option(post_no_edit),
- X '\0',
- X};
- X
- Xdo_nnpost(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int ngroups, i;
- X char newsgroups[FILENAME*2];
- X
- X init_term();
- X visit_init_file(0, (char *)NULL);
- X current_group = NULL;
- X
- X ngroups =
- X parse_options(argc, argv, (char *)NULL, post_options,
- X " newsgroup...");
- X
- X if (post_no_edit && post_source_file == NULL) {
- X printf("Must specify a source file with -p\n");
- X nn_exit(1);
- X }
- X
- X if (ngroups > 0) {
- X strcpy(newsgroups, argv[1]);
- X for (i = 2; i <= ngroups; i++) {
- X strcat(newsgroups, ",");
- X strcat(newsgroups, argv[i]);
- X }
- X post_to_groups = newsgroups;
- X }
- X
- X raw();
- X clrdisp();
- X prompt_line = 0;
- X post_menu();
- X putchar(CR); putchar(NL);
- X unset_raw();
- X if (*delayed_msg)
- X printf("%s\n", delayed_msg);
- X
- X nn_exit(0);
- X}
- X
- Xpost_menu()
- X{
- X register FILE *t, *src;
- X register int c;
- X char *str, *tail;
- X char group_name[FILENAME], subject[FILENAME],
- X distribution[FILENAME], keywords[FILENAME], summary[FILENAME];
- X extern group_completion();
- X
- X if (post_source_file) {
- X src = open_file(post_source_file, OPEN_READ);
- X if (src == NULL) {
- X printf("File %s not found\n");
- X nn_exit(1);
- X }
- X }
- X
- X if (post_to_groups)
- X strcpy(group_name, post_to_groups);
- X else {
- X group_name[0] = NUL;
- X
- X again_group:
- X
- X prompt(who_am_i == I_AM_POST ? "Newsgroups: " : "\1POST to group\1 ");
- X
- X str = get_s(current_group ? current_group->group_name : NONE,
- X group_name, NONE, group_completion);
- X if (str == NULL) return 0;
- X if (*str == NUL) {
- X if (current_group == NULL || (current_group->group_flag & G_FAKED))
- X return 0;
- X str = current_group->group_name;
- X }
- X strcpy(group_name, str);
- X
- X for (str = group_name; str; str = tail) {
- X tail = strchr(str, ',');
- X if (tail) *tail = NUL;
- X
- X if (lookup(str) == NULL) {
- X msg("unknown group: %s", str);
- X *str = NUL;
- X goto again_group;
- X }
- X
- X if (tail) *tail++ = ',';
- X }
- X if (who_am_i == I_AM_POST) prompt_line++;
- X }
- X
- X if ((str = post_subject) == NULL) {
- X prompt("Subject: ");
- X str = get_s(NONE, NONE, NONE, NULL_FCT);
- X if (str == NULL || *str == NUL) return 0;
- X if (who_am_i == I_AM_POST) prompt_line++;
- X }
- X strcpy(subject, str);
- X
- X if ((str = post_keywords) == NULL) {
- X prompt("Keywords: ");
- X str = get_s(NONE, NONE, NONE, NULL_FCT);
- X if (str == NULL) return 0;
- X if (who_am_i == I_AM_POST) prompt_line++;
- X }
- X strcpy(keywords, str);
- X
- X if ((str = post_summary) == NULL) {
- X prompt("Summary: ");
- X str = get_s(NONE, NONE, NONE, NULL_FCT);
- X if (str == NULL) return 0;
- X if (who_am_i == I_AM_POST) prompt_line++;
- X }
- X strcpy(summary, str);
- X
- X if (post_distribution) {
- X strcpy(distribution, post_distribution);
- X } else {
- X if (default_distribution != NULL)
- X strcpy(distribution, default_distribution);
- X else {
- X strcpy(distribution, group_name);
- X if (str = strchr(distribution, ',')) *str = NUL;
- X if (str = strchr(distribution, '.')) *str = NUL;
- X }
- X
- X prompt("Distribution: (default '%s') ", distribution);
- X str = get_s(NONE, NONE, NONE, NULL_FCT);
- X if (str == NULL) return 0;
- X if (*str) strcpy(distribution, str);
- X if (who_am_i == I_AM_POST) prompt_line++;
- X }
- X
- X new_temp_file();
- X if ((t = open_file(temp_file, OPEN_CREATE)) == NULL) {
- X msg("Can't create %s", temp_file);
- X return 0;
- X }
- X
- X if (!post_no_edit)
- X prompt("\1WAIT\1");
- X
- X ed_line = 3;
- X#ifdef NNTP
- X#ifdef NNTP_MINI_INEWS_HEADER
- X mini_inews_header(t);
- X#endif
- X#endif
- X fprintf(t, "Newsgroups: %s\n", group_name);
- X fprintf(t, "Distribution: %s\n", distribution);
- X fprintf(t, "Subject: %s\n", subject);
- X if (*summary) {
- X fprintf(t, "Summary: %s\n", summary);
- X ed_line++;
- X }
- X if (*keywords) {
- X fprintf(t, "Keywords: %s\n", keywords);
- X ed_line++;
- X }
- X
- X end_header(t, extra_news_headers);
- X
- X if (post_source_file) {
- X while ((c = getc(src)) != EOF) putc(c, t);
- X fclose(src);
- X } else
- X fputc(NL, t);
- X
- X fclose(t);
- X
- X aux_sh((article_header *)NULL, news_script, "post",
- X post_no_edit ? "send" : "edit", news_record,
- X "Article%s posted", append_sig_post);
- X
- X return 1;
- X}
- X
- END_OF_FILE
- if test 18768 -ne `wc -c <'answer.c'`; then
- echo shar: \"'answer.c'\" unpacked with wrong size!
- fi
- # end of 'answer.c'
- fi
- if test -f 'conf/s-aix221.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'conf/s-aix221.h'\"
- else
- echo shar: Extracting \"'conf/s-aix221.h'\" \(447 characters\)
- sed "s/^X//" >'conf/s-aix221.h' <<'END_OF_FILE'
- X/*
- X * This version is for AIX 2.2.1
- X * From: marcel@duteca.tudelft.nl (Marcel J.E. Mol)
- X */
- X
- X/*
- X * Notice: AIX's PRINTER command is "print" (see config.h)
- X */
- X
- X#include <s-sys5.h>
- X
- X/*
- X * AIX does have void signal handlers, but
- X * a typedef void does not work
- X */
- X
- X#undef SIGNAL_HANDLERS_ARE_VOID
- X
- X/*
- X * Define HAVE_GETHOSTNAME if your system provides a BSD like
- X * gethostname routine.
- X */
- X
- X#undef HAVE_UNAME
- X#define HAVE_GETHOSTNAME
- X
- END_OF_FILE
- if test 447 -ne `wc -c <'conf/s-aix221.h'`; then
- echo shar: \"'conf/s-aix221.h'\" unpacked with wrong size!
- fi
- # end of 'conf/s-aix221.h'
- fi
- if test -f 'macro.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'macro.c'\"
- else
- echo shar: Extracting \"'macro.c'\" \(14186 characters\)
- sed "s/^X//" >'macro.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- X *
- X * Macro parsing and execution.
- X */
- X
- X#include "config.h"
- X#include "keymap.h"
- X#include "term.h"
- X
- Xexport int in_menu_mode = 0;
- Xexport int get_from_macro = 0;
- Xexport int macro_debug = 0;
- Xexport char *dflt_enter_macro = NULL;
- X
- X#define M_DUMMY 0 /* do nothing (end of branch) */
- X
- X#define M_COMMAND 1 /* a command (get_c()) */
- X#define M_KEY 2 /* a key stroke (get_c()) */
- X#define M_STRING 3 /* a string (get_s()) */
- X
- X#define M_INPUT 4 /* take input from keyboard (get_c/get_s) */
- X
- X#define M_YES 5 /* answer yes to confirmation */
- X#define M_NO 6 /* answer no to confirmation and break */
- X /* -- if neither are present, take input */
- X
- X#define M_PUTS 7 /* puts "..." */
- X#define M_PROMPT 8 /* prompt(...) */
- X#define M_ECHO 9 /* msg(...) */
- X
- X#define M_IS_MENU 10 /* in menu mode ? */
- X#define M_IS_SHOW 11 /* in reading mode ? */
- X#define M_IS_GROUP 12 /* are we in a news group ? */
- X#define M_IS_FOLDER 13 /* are we in a folder ? */
- X#define M_CONFIRM 14 /* ask for confirmation to procede */
- X#define M_REJECT 15 /* ask for !confirmation to procede */
- X#define M_VARTEST 16 /* test value of variable */
- X#define M_BREAK 17 /* exit from macroes */
- X#define M_RETURN 18 /* return from this macro */
- X
- X#define M_SET_COMMAND 19 /* set/unset command */
- X
- X
- Xstruct macro {
- X int m_type; /* entry type */
- X union {
- X int mu_int; /* command or char */
- X char *mu_string; /* string for get_s */
- X struct macro *mu_branch; /* false conditional */
- X } m_value;
- X struct macro *m_next; /* next macro element */
- X};
- X
- X#define m_int m_value.mu_int
- X#define m_string m_value.mu_string
- X#define m_branch m_value.mu_branch
- X
- X#define NUM_MACRO 101 /* numbered macros */
- X#define ANON_MACRO 100 /* anonymous macroes */
- X#define NMACRO (NUM_MACRO + ANON_MACRO)
- X
- X#define MSTACK 5 /* max nesting level */
- X
- Xstatic struct macro *macro[NMACRO + 1]; /* macro table */
- X /* the extra slot is for entry macroes */
- X
- Xstatic struct macro *mstack[MSTACK]; /* macro stack */
- Xstatic int cstack[MSTACK + 1];
- Xstatic int m_level = 0;
- X
- Xstatic struct macro *m = NULL; /* current macro */
- Xstatic int no_advance = 0;
- Xstatic int changed_prompt = 0;
- X
- Xstatic int cur_m;
- X
- X#define MERROR ((struct macro *)1)
- X
- Xstatic m_error(fmt, arg)
- Xchar *fmt, *arg;
- X{
- X char buf[80];
- X
- X if (arg) {
- X sprintf(buf, fmt, arg);
- X fmt = buf;
- X }
- X
- X init_message("Error in macro %d: %s", cur_m, fmt);
- X}
- X
- Xinit_macro()
- X{
- X int n;
- X
- X for (n = 0; n <= NMACRO; n++)
- X macro[n] = NULL;
- X}
- X
- Xstatic m_new(t)
- Xint t;
- X{
- X struct macro *m1;
- X
- X m1 = newobj(struct macro, 1);
- X
- X if (m == NULL)
- X m = macro[cur_m] = m1;
- X else {
- X m->m_next = m1;
- X m = m1;
- X }
- X m->m_type = t;
- X m->m_next = NULL;
- X}
- X
- X
- X/*
- X * Define macro "id" reading from file f until "end"
- X *
- X * Macro definition syntax:
- X * define <id>
- X * <body>
- X * end
- X *
- X * Id string interpretation:
- X * NULL use next free numbered macro
- X * Return: pointer to macro
- X * "nnn" nnn>=0 Numbered macro nnn
- X * Return: pointer to macro
- X * "-1" entry macro
- X * Return: pointer to macro
- X * "-2" anonymous macro
- X * Return: K_MACRO code or K_UNBOUND on error
- X */
- X
- Xstatic int initial_set_commands;
- X
- Xstatic parse_word(w)
- Xchar *w;
- X{
- X int cmd;
- X register struct macro *m1;
- X
- X if (m && m->m_type == M_COMMAND && m->m_int == (GETC_COMMAND | K_MACRO)) {
- X if (isdigit(*w)) {
- X m->m_int |= atoi(w);
- X goto ok;
- X }
- X m_error("macro number missing", (char *)NULL);
- X return 1;
- X }
- X
- X if (*w == '"') {
- X if (m == NULL || (m->m_type != M_PROMPT && m->m_type != M_ECHO && m->m_type != M_PUTS))
- X m_new(M_STRING);
- X m->m_string = copy_str(w + 1);
- X goto ok;
- X }
- X
- X if (*w == '\'') {
- X m_new(M_KEY);
- X m->m_int = parse_key(w + 1);
- X goto ok;
- X }
- X
- X if (*w == '?') {
- X if (strchr(w, '=')) {
- X m->m_type = M_VARTEST;
- X m1 = m;
- X m_new(M_DUMMY);
- X m->m_branch = m1->m_branch;
- X m1->m_string = copy_str(w + 1);
- X goto ok;
- X }
- X
- X switch (w[1]) {
- X case 'f': /* ?folder */
- X cmd = M_IS_FOLDER;
- X break;
- X case 'g': /* ?group */
- X cmd = M_IS_GROUP;
- X break;
- X case 'm': /* ?menu */
- X cmd = M_IS_MENU;
- X break;
- X case 'n': /* ?no */
- X cmd = M_REJECT;
- X break;
- X case 's': /* ?show */
- X cmd = M_IS_SHOW;
- X break;
- X case 'y': /* ?yes */
- X cmd = M_CONFIRM;
- X break;
- X default:
- X m_error("unknown conditional %s", w - 1);
- X return 1;
- X }
- X m->m_type = cmd;
- X goto ok;
- X }
- X
- X if ((cmd = lookup_command(w, (K_ONLY_MENU | K_ONLY_MORE))) != K_INVALID) {
- X m_new(M_COMMAND);
- X m->m_int = GETC_COMMAND | cmd;
- X goto ok;
- X }
- X
- X if (strcmp(w, "prompt") == 0) {
- X m_new(M_PROMPT);
- X m->m_string = "?";
- X goto ok;
- X }
- X if (strcmp(w, "echo") == 0) {
- X m_new(M_ECHO);
- X m->m_string = "ups";
- X goto ok;
- X }
- X if (strcmp(w, "puts") == 0) {
- X m_new(M_PUTS);
- X m->m_string = "";
- X goto ok;
- X }
- X if (strcmp(w, "input") == 0) {
- X m_new(M_INPUT);
- X goto ok;
- X }
- X if (strcmp(w, "yes") == 0) {
- X m_new(M_YES);
- X goto ok;
- X }
- X if (strcmp(w, "no") == 0) {
- X m_new(M_NO);
- X goto ok;
- X }
- X if (strcmp(w, "break") == 0) {
- X m_new(M_BREAK);
- X goto ok;
- X }
- X if (strcmp(w, "return") == 0) {
- X m_new(M_RETURN);
- X goto ok;
- X }
- X
- X m_error("Unknown word >>%s<<", w);
- X return 1;
- X
- X ok:
- X return 0;
- X}
- X
- Xstatic parse_line(lp)
- Xchar *lp;
- X{
- X char *word;
- X struct macro *m1, *branch = NULL;
- X
- X while (*lp) {
- X if (*lp == '#') break;
- X
- X if (*lp == ':') {
- X lp++;
- X if (initial_set_commands) {
- X if (strncmp(lp, "local", 5) == 0 ||
- X strncmp(lp, "set", 3) == 0 ||
- X strncmp(lp, "unset", 5) == 0) {
- X m_new(M_SET_COMMAND);
- X m->m_string = copy_str(lp);
- X break;
- X }
- X initial_set_commands = 0;
- X }
- X m_new(M_COMMAND);
- X m->m_int = GETC_COMMAND | K_EXTENDED_CMD;
- X m_new(M_STRING);
- X m->m_string = copy_str(lp);
- X break;
- X }
- X initial_set_commands = 0;
- X
- X if (*lp == '?') {
- X m_new(M_IS_MENU);
- X if (branch == NULL) {
- X m1 = m;
- X m_new(M_DUMMY);
- X branch = m;
- X m = m1;
- X }
- X m->m_branch = branch;
- X }
- X
- X word = lp;
- X if (*lp == '"')
- X do lp++;
- X while (*lp && *lp != '"');
- X else
- X if (*lp == '\'')
- X do lp++;
- X while (*lp && *lp != '\'');
- X else
- X while (*lp && !isspace(*lp)) lp++;
- X if (*lp) {
- X *lp++ = NUL;
- X while (*lp && isspace(*lp)) lp++;
- X }
- X if (parse_word(word)) return 1;
- X }
- X
- X if (branch) {
- X m->m_next = branch;
- X m = branch;
- X }
- X return 0;
- X}
- X
- Xchar *m_define(id, f)
- Xchar *id;
- XFILE *f;
- X{
- X char line[256], *lp, skip;
- X int type = 0;
- X
- X if (id) {
- X cur_m = atoi(id);
- X if (cur_m == -1) {
- X cur_m = NMACRO; /* special slot for this purpose */
- X } else if (cur_m == -2) {
- X for (cur_m = NUM_MACRO; cur_m < NMACRO; cur_m++)
- X if (macro[cur_m] == NULL) break;
- X if (cur_m == NMACRO) {
- X init_message("No unused macro slots");
- X return (char *)K_UNBOUND;
- X }
- X type = 1;
- X } else if (cur_m < 0 || cur_m >= NUM_MACRO) {
- X m_error("macro number out of range\n", id);
- X return (char *)0;
- X }
- X } else {
- X for (cur_m = 0; cur_m < NUM_MACRO; cur_m++)
- X if (macro[cur_m] == NULL) break;
- X if (cur_m == NUM_MACRO) {
- X init_message("No unused macro numbers");
- X return (char *)0;
- X }
- X }
- X
- X if (f == NULL) {
- X clrdisp();
- X printf("DEFINE %sMACRO %d -- END WITH 'end'\n\n\r",
- X cur_m >= NUM_MACRO ? "ANONYMOUS " : "",
- X cur_m >= NUM_MACRO ? cur_m - NUM_MACRO : cur_m);
- X unset_raw();
- X f = stdin;
- X }
- X
- X m = NULL;
- X skip = 0;
- X initial_set_commands = (cur_m == NMACRO);
- X
- X while (fgets(line, 256, f)) {
- X for (lp = line; *lp && isspace(*lp); lp++);
- X if (*lp == NUL) continue;
- X if (*lp == ')' || strncmp(lp, "end", 3) == 0) goto out;
- X if (!skip && parse_line(lp)) {
- X macro[cur_m] = NULL;
- X skip++;
- X }
- X }
- X
- X if (f != stdin)
- X m_error("end missing", (char *)NULL);
- X
- X out:
- X if (f == stdin) raw();
- X m = NULL;
- X return type == 0 ? (char *)macro[cur_m] : (char *)(K_MACRO | cur_m);
- X}
- X
- Xchar *m_get_macro(id)
- Xchar *id;
- X{
- X if (id) {
- X cur_m = atoi(id);
- X if (cur_m < 0 || cur_m >= NMACRO) {
- X m_error("macro number out of range\n", id);
- X return (char *)0;
- X }
- X }
- X return (char *)macro[cur_m];
- X}
- X
- Xchar *parse_enter_macro(f, c)
- XFILE *f;
- Xregister int c;
- X{
- X register char *gp;
- X char other[FILENAME];
- X group_header *gh;
- X static char *last_defined = NULL;
- X
- X while (c != EOF && c != NL && (!isascii(c) || isspace(c))) c = getc(f);
- X
- X if (c == ')') return last_defined;
- X
- X if (c == EOF) return (char *)NULL;
- X
- X if (c == NL) return last_defined = m_define("-1", f);
- X
- X gp = other;
- X do {
- X *gp++ = c;
- X c = getc(f);
- X } while (c != EOF && c != ')' && isascii(c) && !isspace(c));
- X
- X *gp = NUL;
- X if (gh = lookup(other)) return gh->enter_macro;
- X
- X return m_get_macro(other);
- X}
- X
- X/*
- X * Invoke macro # N
- X */
- X
- Xm_invoke(n)
- Xint n;
- X{
- X if (n < 0) {
- X n = NMACRO;
- X if ((macro[n] = (struct macro *)(current_group->enter_macro)) == NULL)
- X if ((macro[n] = (struct macro *)dflt_enter_macro) == NULL)
- X return;
- X } else
- X if (n >= NMACRO || macro[n] == NULL) {
- X msg("undefined macro %d", n);
- X return;
- X }
- X
- X if (m_level == 0)
- X no_advance = 0;
- X else {
- X if (m_level > MSTACK) {
- X msg("Macro stack overflow");
- X m_break();
- X return;
- X }
- X mstack[m_level] = m;
- X cstack[m_level] = cur_m;
- X }
- X m_level++;
- X
- X cur_m = n;
- X m = macro[cur_m];
- X while (m && m->m_type == M_SET_COMMAND) {
- X char buffer[128];
- X strcpy(buffer, m->m_string);
- X if (macro_debug) { msg(":%s", buffer); user_delay(1); }
- X parse_command(buffer, 0, (FILE *)NULL);
- X m = m->m_next;
- X }
- X}
- X
- Xm_startinput()
- X{
- X no_advance = 1;
- X}
- X
- Xm_endinput()
- X{
- X if (no_advance) {
- X no_advance = 0;
- X if (m && m->m_type == M_INPUT)
- X m = m->m_next;
- X }
- X}
- X
- Xm_advinput()
- X{
- X if (m && m->m_type == M_INPUT)
- X m = m->m_next;
- X}
- X
- Xstatic struct macro *m_call(who)
- Xint who;
- X{
- X struct macro *m1;
- X
- X for (;;) {
- X while (m == NULL && m_level > 1) {
- X m_level--;
- X m = mstack[m_level];
- X cur_m = cstack[m_level];
- X }
- X if (m == NULL) {
- X if (macro_debug) msg("end");
- X m_break();
- X return NULL;
- X }
- X
- X if (macro_debug)
- X macro_dbg();
- X
- X if (who == 3) {
- X if (m->m_type == M_YES || m->m_type == M_NO) goto out;
- X return NULL;
- X }
- X
- X switch (m->m_type) {
- X case M_COMMAND:
- X if (m->m_int == (GETC_COMMAND | K_REDRAW))
- X changed_prompt = 0;
- X case M_KEY:
- X if (who == 1) goto out;
- X goto err;
- X
- X case M_STRING:
- X if (who == 2) goto out;
- X goto err;
- X
- X case M_INPUT:
- X if (no_advance) return m;
- X goto out;
- X
- X case M_YES:
- X case M_NO:
- X case M_DUMMY:
- X break;
- X
- X case M_PUTS:
- X fputs(m->m_string, stdout); fl;
- X break;
- X
- X case M_PROMPT:
- X if (m->m_string[0] == NUL) {
- X changed_prompt = 0;
- X break;
- X }
- X if (!changed_prompt) prompt(P_SAVE);
- X changed_prompt = 1;
- X prompt("\1%s\1 ", m->m_string);
- X break;
- X
- X case M_ECHO:
- X msg(m->m_string);
- X restore_xy();
- X break;
- X
- X case M_IS_MENU:
- X if (!in_menu_mode) m = m->m_branch;
- X break;
- X case M_IS_SHOW:
- X if (in_menu_mode) m = m->m_branch;
- X break;
- X case M_IS_GROUP:
- X if (current_group->group_flag & G_FOLDER) m = m->m_branch;
- X break;
- X case M_IS_FOLDER:
- X if ((current_group->group_flag & G_FOLDER) == 0) m = m->m_branch;
- X break;
- X case M_CONFIRM:
- X if (yes(0) == 0) m = m->m_branch;
- X break;
- X case M_REJECT:
- X if (yes(0) == 1) m = m->m_branch;
- X break;
- X
- X case M_VARTEST:
- X m1 = m;
- X m = m->m_next;
- X
- X switch (test_variable(m1->m_string)) {
- X case 0:
- X m = m->m_branch;
- X break;
- X case -1:
- X goto err1;
- X }
- X break;
- X
- X case M_RETURN:
- X m = NULL;
- X continue;
- X
- X case M_BREAK:
- X goto term;
- X }
- X
- X if (m) m = m->m_next;
- X }
- X
- X out:
- X m1 = m;
- X m = m->m_next;
- X no_advance = 0;
- X return m1;
- X
- X err:
- X msg("Error in macro %d", cur_m);
- X err1:
- X user_delay(1);
- X m_break();
- X return MERROR;
- X
- X term:
- X m_break();
- X return NULL;
- X}
- X
- Xm_break_entry()
- X{
- X if (current_group->enter_macro || dflt_enter_macro)
- X m = NULL;
- X}
- X
- Xm_break()
- X{
- X if (changed_prompt) prompt(P_RESTORE);
- X changed_prompt = 0;
- X m = NULL;
- X m_level = 0;
- X}
- X
- Xmacro_dbg()
- X{
- X extern char *command_name();
- X char *name;
- X
- X switch (m->m_type) {
- X case M_COMMAND:
- X msg("COMMAND: %s", command_name(m->m_int));
- X goto delay;
- X
- X case M_KEY:
- X msg("KEY: %s", key_name((key_type)(m->m_int)));
- X goto delay;
- X
- X case M_STRING:
- X msg("STRING: %s", m->m_string);
- X goto delay;
- X
- X case M_INPUT:
- X name = "input";
- X break;
- X
- X case M_YES:
- X name = "yes";
- X break;
- X
- X case M_NO:
- X name = "no";
- X break;
- X
- X case M_DUMMY:
- X name = "dummy";
- X break;
- X
- X case M_PROMPT:
- X msg("PROMPT: %s", m->m_string);
- X goto delay;
- X
- X case M_ECHO:
- X msg("ECHO: %s", m->m_string);
- X goto delay;
- X
- X case M_IS_MENU:
- X msg("?menu => %d", in_menu_mode);
- X goto delay;
- X
- X case M_IS_SHOW:
- X msg("?show => %d", !in_menu_mode);
- X goto delay;
- X
- X case M_IS_GROUP:
- X msg("?group => %d", (current_group->group_flag & G_FOLDER) == 0);
- X goto delay;
- X
- X case M_IS_FOLDER:
- X msg("?group => %d", (current_group->group_flag & G_FOLDER));
- X goto delay;
- X
- X case M_CONFIRM:
- X name = "?yes";
- X break;
- X
- X case M_REJECT:
- X name = "?no";
- X break;
- X
- X case M_VARTEST:
- X msg("?%s => %d", m->m_string, test_variable(m->m_string));
- X goto delay;
- X
- X case M_RETURN:
- X name = "return";
- X break;
- X
- X case M_BREAK:
- X name = "break";
- X break;
- X }
- X msg(name);
- X
- X delay:
- X user_delay(1);
- X}
- X
- X/*
- X * Macro processing for get_c()
- X */
- X
- Xm_getc(cp)
- Xint *cp;
- X{
- X struct macro *m1;
- X
- X get_from_macro = 0;
- X if (m_level && (m1 = m_call(1))) {
- X if (m1 == MERROR) return 2;
- X if (m1->m_type == M_INPUT) return 0;
- X *cp = m1->m_int;
- X get_from_macro = 1;
- X return 1;
- X }
- X return 0;
- X}
- X
- X/*
- X * Macro processing for get_s()
- X */
- X
- Xm_gets(s)
- Xchar *s;
- X{
- X struct macro *m1;
- X
- X get_from_macro = 0;
- X if (m_level && (m1 = m_call(2))) {
- X if (m1 == MERROR) return 2;
- X if (m1->m_type == M_INPUT) return 0;
- X strcpy(s, m1->m_string);
- X get_from_macro = 1;
- X return 1;
- X }
- X return 0;
- X}
- X
- X/*
- X * Macro processing for yes()
- X */
- X
- Xm_yes()
- X{
- X struct macro *m1;
- X
- X if (m)
- X if (m->m_type == M_CONFIRM || m->m_type == M_REJECT) return 3;
- X
- X if (m_level) {
- X if (m1 = m_call(3))
- X if (m1->m_type == M_NO)
- X return 1;
- X else
- X return 2;
- X else
- X return 3;
- X }
- X return 0;
- X}
- END_OF_FILE
- if test 14186 -ne `wc -c <'macro.c'`; then
- echo shar: \"'macro.c'\" unpacked with wrong size!
- fi
- # end of 'macro.c'
- fi
- if test -f 'nn.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'nn.c'\"
- else
- echo shar: Extracting \"'nn.c'\" \(17064 characters\)
- sed "s/^X//" >'nn.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- X *
- X * The nn user interface main program
- X */
- X
- X#include "config.h"
- X#include "menu.h"
- X#include "term.h"
- X#include "keymap.h"
- X#include "options.h"
- X#include "proto.h"
- X#include "articles.h"
- X
- Ximport char *bin_directory;
- X
- Ximport int
- X seq_cross_filtering, /* articles */
- X dont_sort_folders, /* folder.c */
- X dont_split_digests, dont_sort_articles, also_unsub_groups, /* group.c */
- X also_cross_postings,
- X case_fold_search, /* match.c */
- X preview_window, fmt_linenum, fmt_rptsubj, /* menu.c */
- X show_article_date, first_page_lines, /* more.c */
- X keep_rc_backup, no_update, /* newsrc.c */
- X hex_group_args, /* sequence */
- X show_current_time, conf_dont_sleep; /* term.c */
- X
- Xexport int
- X article_limit = -1,
- X also_read_articles = 0,
- X conf_auto_quit = 0,
- X do_kill_handling = 1,
- X group_name_args = 0,
- X merged_menu = 0,
- X repeat_group_query = 0,
- X report_cost_on_exit = 1,
- X silent = 0,
- X verbose = 0,
- X Debug = 0;
- X
- Xstatic int
- X nngrab_mode = 0,
- X prompt_for_group = 0;
- X
- Xstatic char
- X *match_subject = NULL,
- X *match_sender = NULL,
- X *init_file = NULL;
- X
- XOption_Description(nn_options) {
- X 'a', Int_Option(article_limit),
- X 'B', Bool_Option(keep_rc_backup),
- X 'd', Bool_Option(dont_split_digests),
- X 'f', Bool_Option(dont_sort_folders),
- X 'g', Bool_Option(prompt_for_group),
- X 'G', Bool_Option(nngrab_mode),
- X 'i', Bool_Option(case_fold_search),
- X 'I', String_Option_Optional(init_file, NULL),
- X 'k', Bool_Option(do_kill_handling),
- X 'l', Int_Option(first_page_lines),
- X 'L', Int_Option_Optional(fmt_linenum, 3),
- X 'm', Bool_Option(merged_menu),
- X 'n', String_Option(match_sender),
- X 'N', Bool_Option(no_update),
- X 'q', Bool_Option(dont_sort_articles),
- X 'Q', Bool_Option(silent),
- X 'r', Bool_Option(repeat_group_query),
- X 's', String_Option(match_subject),
- X 'S', Bool_Option(fmt_rptsubj),
- X 'T', Bool_Option(show_current_time),
- X 'w', Int_Option_Optional(preview_window, 5),
- X 'W', Bool_Option(conf_dont_sleep),
- X 'x', Int_Option_Optional(also_read_articles, -1),
- X 'X', Bool_Option(also_unsub_groups),
- X 'Z', Int_Option(Debug),
- X '\0',
- X};
- X
- X
- Xstatic int
- X report_number_of_articles = 0;
- Xstatic char
- X *check_message_format = NULL;
- Ximport int
- X quick_unread_count;
- X
- XOption_Description(check_options) {
- X 'Q', Bool_Option(silent),
- X 'r', Bool_Option(report_number_of_articles),
- X 'f', String_Option(check_message_format),
- X 't', Bool_Option(verbose),
- X 'v', Bool_Option(verbose),
- X 'c', Bool_Option(quick_unread_count),
- X '\0',
- X};
- X
- X/* program name == argv[0] without path */
- X
- Xchar *pname;
- X
- Xstatic int must_unlock = 0;
- X
- Xstatic int nn_locked()
- X{
- X if (no_update) return 0;
- X
- X switch (who_am_i) {
- X case I_AM_ADMIN:
- X case I_AM_CHECK:
- X case I_AM_POST:
- X case I_AM_GREP:
- X case I_AM_SPEW:
- X return 0; /* will not update .newsrc */
- X }
- X
- X if (proto_lock(I_AM_NN, PL_SET)) {
- X printf("\nAnother nn process is already running\n\n");
- X return 1;
- X }
- X
- X must_unlock = 1;
- X return 0;
- X}
- X
- Xstatic flag_type setup_access()
- X{
- X flag_type access_mode = 0;
- X
- X if (do_kill_handling)
- X access_mode |= ACC_DO_KILL;
- X if (also_cross_postings)
- X access_mode |= ACC_ALSO_CROSS_POSTINGS;
- X if (also_read_articles)
- X access_mode |= ACC_ALSO_READ_ARTICLES;
- X if (dont_split_digests)
- X access_mode |= ACC_DONT_SPLIT_DIGESTS;
- X if (dont_sort_articles)
- X access_mode |= ACC_DONT_SORT_ARTICLES;
- X
- X return access_mode;
- X}
- X
- Xexport group_header *jump_to_group = NULL;
- X
- Xstatic read_news(access_mode, mask)
- Xflag_type access_mode;
- Xchar *mask;
- X{
- X register group_header *gh, *prev, *tmp, *after_loop;
- X flag_type group_mode;
- X int menu_cmd;
- X int must_clear = 0, did_jump = 0;
- X extern int menu();
- X
- X prev = group_sequence;
- X gh = group_sequence;
- X after_loop = NULL;
- X
- X for (;;) {
- X group_mode = access_mode;
- X
- X if (s_hangup) break;
- X
- X if (gh == NULL) {
- X if (after_loop != NULL) {
- X gh = after_loop;
- X after_loop = NULL;
- X if (gh->unread_count <= 0)
- X group_mode |= ACC_ORIG_NEWSRC;
- X goto enter_direct;
- X }
- X
- X if (did_jump) {
- X did_jump = 0;
- X gh = group_sequence;
- X continue;
- X }
- X
- X if (must_clear && conf_auto_quit) {
- X prompt("\1LAST GROUP READ. QUIT NOW?\1");
- X switch (yes(1)) {
- X case 1:
- X break;
- X case 0:
- X gh = group_sequence;
- X default:
- X after_loop = prev;
- X continue;
- X }
- X }
- X break;
- X }
- X
- X if (gh->group_flag & G_UNSUBSCRIBED) {
- X if (!also_unsub_groups) {
- X gh = gh->next_group;
- X continue;
- X }
- X } else
- X if (!also_read_articles && gh->unread_count <= 0) {
- X gh = gh->next_group;
- X continue;
- X }
- X
- X enter_direct:
- X
- X free_memory();
- X
- X if (gh->group_flag & G_FOLDER) {
- X menu_cmd = folder_menu(gh->group_name);
- X if (menu_cmd == ME_NO_REDRAW) {
- X menu_cmd = ME_NO_ARTICLES;
- X gh->last_db_article = 0;
- X }
- X } else {
- X group_mode |= setup_access();
- X if (group_mode & ACC_ORIG_NEWSRC)
- X gh->last_article = gh->first_article;
- X
- X menu_cmd = group_menu(gh, (article_number)(-1), group_mode, mask, menu);
- X group_mode = access_mode;
- X }
- X
- X if (menu_cmd != ME_NO_ARTICLES) {
- X after_loop = NULL;
- X must_clear++;
- X }
- X
- X switch (menu_cmd) {
- X
- X case ME_QUIT: /* or jump */
- X if (!jump_to_group) return must_clear;
- X
- X prev = jump_to_group;
- X jump_to_group = NULL;
- X did_jump = 1;
- X /* fall thru */
- X
- X case ME_PREV:
- X tmp = gh;
- X gh = prev;
- X prev = tmp;
- X if (gh->unread_count <= 0)
- X group_mode |= ACC_ORIG_NEWSRC;
- X goto enter_direct;
- X
- X case ME_NEXT:
- X prev = gh;
- X /* fall thru */
- X
- X case ME_NO_ARTICLES:
- X if (gh->group_flag & G_MERGE_HEAD) {
- X do gh = gh->next_group;
- X while (gh && (gh->group_flag & G_MERGE_SUB));
- X } else
- X gh = gh->next_group;
- X continue;
- X }
- X }
- X return must_clear;
- X}
- X
- X
- Xstatic catch_up()
- X{
- X register group_header *gh;
- X char answer[50];
- X int mode, must_help;
- X import int newsrc_update_freq, novice;
- X import int menu();
- X flag_type access_mode;
- X
- X access_mode = setup_access();
- X
- X prt_unread("\nCatch-up on %u ? (auto)matically (i)nteractive ");
- X fl;
- X mode = 0;
- X
- X if (gets(answer)) {
- X if (strncmp(answer, "auto", 4) == 0) {
- X printf("\nUPDATING .newsrc FILE....");
- X fl;
- X mode = -1;
- X } else
- X if (*answer == 'i')
- X mode = 1;
- X }
- X
- X if (mode == 0) {
- X printf("\nNO UPDATE\n");
- X return;
- X }
- X
- X newsrc_update_freq = 9999;
- X must_help = novice;
- X
- X Loop_Groups_Sequence(gh) {
- X
- X if ((gh->group_flag & G_COUNTED) == 0) continue;
- X
- X if (mode < 0) {
- X update_rc_all(gh, 0);
- X continue;
- X }
- X
- X again:
- X if (must_help) {
- X printf("\n y - mark all articles as read in current group\n");
- X printf(" n - do not update group\n");
- X printf(" r - read the group now\n");
- X printf(" U - unsubscribe to current group\n");
- X printf(" ? - this message\n");
- X printf(" q - quit\n\n");
- X
- X must_help = 0;
- X }
- X
- X printf("Update %s (%ld)? (ynrU?q) n\b", gh->group_name,
- X (long)(gh->last_db_article - gh->last_article));
- X fl;
- X
- X if (gets(answer) == NULL || s_keyboard)
- X *answer = 'q';
- X
- X switch (*answer) {
- X
- X case 'q':
- X putchar(NL);
- X printf("Update rest? (yn) n\b");
- X fl;
- X if (gets(answer) == NULL || *answer != 'y')
- X return;
- X
- X mode = -1;
- X break;
- X
- X case NUL:
- X case 'n':
- X continue;
- X
- X case 'r':
- X raw();
- X group_menu(gh, (article_number)(-1), access_mode, (char *)NULL, menu);
- X unset_raw();
- X clrdisp();
- X if (gh->unread_count > 0) goto again;
- X continue;
- X
- X case 'U':
- X update_rc_all(gh, 1);
- X continue;
- X
- X case 'y':
- X break;
- X
- X default:
- X must_help = 1;
- X goto again;
- X }
- X
- X update_rc_all(gh, 0);
- X }
- X
- X printf("DONE\n");
- X
- X flush_newsrc();
- X}
- X
- Xexport char *mail_box = NULL;
- X
- Xunread_mail(t)
- Xtime_t t;
- X{
- X struct stat st;
- X static time_t next = 0;
- X static int any = 0;
- X
- X if (next > t) return any;
- X
- X next = t + 60;
- X any = 0;
- X
- X if (mail_box == NULL ||
- X stat(mail_box, &st) != 0 ||
- X st.st_size == 0 ||
- X st.st_mtime < st.st_atime) return 0;
- X
- X any = 1;
- X
- X return 1;
- X}
- X
- X#ifdef ACCOUNTING
- X#ifndef STATISTICS
- X#define STATISTICS 1
- X#endif
- X#define NEED_ACCOUNT
- X#else
- X#ifdef AUTHORIZE
- X#define NEED_ACCOUNT
- X#endif
- X#endif
- X
- X#ifdef STATISTICS
- Xstatic time_t usage_time = 0;
- Xstatic time_t last_tick = 0;
- X
- Xstop_usage()
- X{
- X last_tick = 0;
- X}
- X
- Xtime_t tick_usage()
- X{
- X register time_t now;
- X
- X now = cur_time();
- X
- X /*
- X * We ignore ticks > 2 minutes because the user has probably
- X * just left the terminal inside nn and done something else
- X */
- X if (last_tick > (now - 120))
- X usage_time += now - last_tick;
- X
- X last_tick = now;
- X return now;
- X}
- X
- Xlog_usage()
- X{
- X#ifdef ACCOUNTING
- X account('U', report_cost_on_exit);
- X#else
- X if (usage_time < (STATISTICS * 60)) return; /* don't log short sessions */
- X
- X usage_time /= 60;
- X log_entry('U', "USAGE %d.%02d", usage_time/60, usage_time%60);
- X#endif
- X}
- X
- X#else
- Xstop_usage()
- X{
- X}
- X
- Xtime_t tick_usage()
- X{
- X return cur_time();
- X}
- X
- Xlog_usage()
- X{
- X}
- X#endif
- X
- X#ifdef NEED_ACCOUNT
- Xaccount(option, report)
- Xchar option;
- Xint report;
- X{
- X char *args[10], **ap;
- X char buf1[16], buf2[16];
- X int ok;
- X
- X if (who_am_i != I_AM_NN && who_am_i != I_AM_POST) return 0;
- X
- X if (report) {
- X putchar(CR); clrline(); fl;
- X }
- X
- X ap = args;
- X *ap++ = "nnacct";
- X if (report) *ap++ = "-r";
- X sprintf(buf1, "-%c%ld", option, (long)usage_time/60);
- X *ap++ = buf1;
- X sprintf(buf2, "-W%d", who_am_i);
- X *ap++ = buf2;
- X *ap++ = NULL;
- X ok = execute(relative(bin_directory, "nnacct"), args, 0);
- X if (option == 'U' && report) putchar(NL);
- X return ok;
- X}
- X#endif
- X
- X/* this will go into emacs_mode.c when it is completed someday */
- X
- Xemacs_mode()
- X{
- X printf("EMACS MODE IS NOT SUPPORTED YET.\n");
- X}
- X
- X
- Xstatic do_nnspew()
- X{
- X register group_header *gh;
- X import int seq_cross_filtering;
- X int ix;
- X
- X ix = 0;
- X Loop_Groups_Header(gh) {
- X if (gh->master_flag & M_IGNORE_GROUP) continue;
- X gh->preseq_index = ++ix;
- X }
- X
- X /* Only output each article once */
- X /* Must also use this mode when using nngrab! */
- X
- X seq_cross_filtering = 1;
- X
- X Loop_Groups_Header(gh) {
- X if (s_hangup) return 1;
- X if (gh->master_flag & M_IGNORE_GROUP) continue;
- X access_group(gh, gh->first_db_article, gh->last_db_article,
- X ACC_DONT_SORT_ARTICLES | ACC_ALSO_FULL_DIGEST |
- X ACC_SPEW_MODE, (char *)NULL);
- X }
- X return 0;
- X}
- X
- X
- Xclean_group(gh)
- Xgroup_header *gh;
- X{
- X}
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern long unread_articles;
- X extern char *program_name();
- X int say_welcome = 0, cmd;
- X flag_type access_mode;
- X char *mask;
- X
- X pname = program_name(argv);
- X
- X if (strcmp(pname, "nnadmin") == 0) {
- X who_am_i = I_AM_ADMIN;
- X } else
- X if (strcmp(pname, "nnemacs") == 0) {
- X who_am_i = I_AM_EMACS;
- X } else
- X if (strcmp(pname, "nncheck") == 0) {
- X who_am_i = I_AM_CHECK;
- X } else
- X if (strcmp(pname, "nntidy") == 0) {
- X who_am_i = I_AM_TIDY;
- X } else
- X if (strcmp(pname, "nngoback") == 0) {
- X who_am_i = I_AM_GOBACK;
- X } else
- X if (strcmp(pname, "nngrep") == 0) {
- X who_am_i = I_AM_GREP;
- X } else
- X if (strcmp(pname, "nnpost") == 0) {
- X who_am_i = I_AM_POST;
- X } else {
- X who_am_i = I_AM_NN;
- X }
- X
- X if (who_am_i == I_AM_NN || (who_am_i == I_AM_ADMIN && argc == 1)) {
- X if (!isatty(0)) {
- X if (who_am_i == I_AM_NN && argc == 2) {
- X if (strcmp(argv[1], "-SPEW") == 0) {
- X who_am_i = I_AM_SPEW;
- X init_global();
- X goto nnspew;
- X }
- X }
- X
- X fprintf(stderr, "Input is not a tty\n");
- X exit(1);
- X }
- X }
- X
- X#ifdef AUTHORIZE
- X init_execute();
- X if (cmd = account('P', 0)) {
- X switch (cmd) {
- X case 1:
- X if (who_am_i == I_AM_POST) {
- X printf("You are not authorized to post news\n");
- X exit(41);
- X }
- X /* ok_to_post = 0; */
- X cmd = 0;
- X break;
- X case 2:
- X printf("You are not authorized to read news\n");
- X break;
- X case 3:
- X printf("You cannot read news at this time\n");
- X break;
- X case 4:
- X printf("Your news reading quota is exceeded\n");
- X break;
- X default:
- X printf("Bad authorization -- reason %d\n", cmd);
- X break;
- X }
- X if (cmd) exit(40 + cmd);
- X }
- X#endif
- X
- X if ((say_welcome = init_global()) < 0) {
- X printf("%s: nn must been invoked to initialize user files\n", pname);
- X nn_exit(1);
- X }
- X
- X#ifdef NNTP
- X nntp_check();
- X#endif
- X
- X init_key_map();
- X#ifndef AUTHORIZE
- X init_execute();
- X#endif
- X init_macro();
- X
- X nnspew:
- X
- X open_master(OPEN_READ);
- X
- X switch (who_am_i) {
- X
- X case I_AM_NN:
- X init_term();
- X
- X if (say_welcome) {
- X display_file("adm.welcome", CLEAR_DISPLAY | CONFIRMATION);
- X clrdisp();
- X }
- X
- X visit_init_file(0, argv[1]);
- X
- X group_name_args =
- X parse_options(argc, argv, (char *)NULL, nn_options,
- X " [group | [+]folder]...");
- X
- X if (also_read_articles) {
- X if (article_limit < 0)
- X article_limit = also_read_articles;
- X do_kill_handling = 0;
- X no_update++;
- X }
- X
- X if (match_subject) {
- X mask = match_subject;
- X access_mode = ACC_ON_SUBJECT;
- X } else if (match_sender) {
- X mask = match_sender;
- X access_mode = ACC_ON_SENDER;
- X } else {
- X mask = NULL;
- X access_mode = 0;
- X }
- X
- X if (mask) {
- X if (case_fold_search) fold_string(mask);
- X no_update++;
- X do_kill_handling = 0;
- X }
- X
- X if (nngrab_mode) {
- X seq_cross_filtering = 1;
- X hex_group_args = 1;
- X no_update = 1;
- X }
- X
- X if (merged_menu) {
- X no_update++;
- X }
- X
- X if (!no_update && group_name_args > 0)
- X no_update = only_folder_args(argv + 1);
- X
- X break;
- X
- X case I_AM_ADMIN:
- X if (argc == 1) {
- X init_term();
- X visit_init_file(0, (char *)NULL);
- X }
- X admin_mode(argv[1]);
- X nn_exit(0);
- X
- X case I_AM_CHECK:
- X visit_init_file(1, (char *)NULL);
- X group_name_args =
- X parse_options(argc, argv, (char *)NULL, check_options,
- X " [group]...");
- X break;
- X
- X case I_AM_EMACS:
- X silent = 1;
- X break;
- X
- X case I_AM_TIDY:
- X visit_init_file(1, (char *)NULL);
- X group_name_args = opt_nntidy(argc, argv);
- X break;
- X
- X case I_AM_GOBACK:
- X group_name_args = opt_nngoback(argc, &argv);
- X break;
- X
- X case I_AM_GREP:
- X visit_init_file(1, (char *)NULL);
- X opt_nngrep(argc, argv);
- X silent = 1;
- X break;
- X
- X case I_AM_POST:
- X do_nnpost(argc, argv);
- X nn_exit(0);
- X
- X case I_AM_SPEW:
- X if (proto_lock(I_AM_SPEW, PL_SET) == 0) {
- X cmd = do_nnspew();
- X proto_lock(I_AM_SPEW, PL_CLEAR);
- X } else
- X cmd = 1; /* don't interfere with other nnspew */
- X nn_exit(cmd);
- X }
- X
- X if (!silent || who_am_i == I_AM_CHECK)
- X printf("Release %s, Kim F. Storm, 1990\n\n", version_id);
- X
- X if (nn_locked()) nn_exit(2);
- X
- X visit_rc_file();
- X
- X if (group_name_args > 0)
- X named_group_sequence(argv + 1);
- X else
- X normal_group_sequence();
- X
- X if (who_am_i != I_AM_TIDY && who_am_i != I_AM_GOBACK)
- X count_unread_articles();
- X
- X switch (who_am_i) {
- X
- X case I_AM_EMACS:
- X prt_unread("%U %G\n");
- X emacs_mode();
- X break;
- X
- X case I_AM_CHECK:
- X if (report_number_of_articles) {
- X prt_unread("%U");
- X break;
- X }
- X
- X if (check_message_format) {
- X if (unread_articles || !silent)
- X prt_unread(check_message_format);
- X } else
- X if (!silent) {
- X if (unread_articles || report_number_of_articles)
- X prt_unread("There %i %u in %g\n");
- X else
- X prt_unread((char *)NULL);
- X }
- X
- X nn_exit( unread_articles ? 0 : 99 );
- X /*NOTREACHED*/
- X
- X case I_AM_TIDY:
- X do_tidy_newsrc();
- X break;
- X
- X case I_AM_GOBACK:
- X do_goback();
- X break;
- X
- X case I_AM_NN:
- X if (unread_articles == 0 &&
- X group_name_args == 0 &&
- X !also_read_articles &&
- X !prompt_for_group) {
- X if (!silent) prt_unread((char *)NULL);
- X break;
- X }
- X
- X if (do_kill_handling)
- X do_kill_handling = init_kill();
- X
- X if (prompt_for_group) {
- X import int also_cross_postings;
- X
- X if (mask != NULL)
- X user_error("Cannot use -s/-n with -g\n\r");
- X
- X also_cross_postings = 1;
- X do {
- X raw();
- X clrdisp();
- X current_group = NULL;
- X prompt_line = 2;
- X cmd = goto_group(K_GOTO_GROUP, (article_header *)NULL, setup_access());
- X
- X } while (repeat_group_query && cmd != ME_QUIT && cmd != ME_NO_REDRAW);
- X clrdisp();
- X unset_raw();
- X break;
- X }
- X
- X if (!no_update && article_limit == 0) {
- X catch_up();
- X break;
- X }
- X
- X if (merged_menu) {
- X merge_and_read(access_mode | setup_access(), mask);
- X clrdisp();
- X break;
- X }
- X
- X if (read_news(access_mode, mask)) {
- X clrdisp();
- X
- X if (master.db_lock[0])
- X printf("Database has been locked:\n%s\n", master.db_lock);
- X
- X if (!also_read_articles &&
- X unread_articles > 0 &&
- X !silent && group_name_args == 0)
- X prt_unread("There %i still %u in %g\n\n\r");
- X break;
- X }
- X gotoxy(0,Lines-1);
- X if (group_name_args == 0)
- X printf("No News\n");
- X else
- X printf("\r\n");
- X break;
- X
- X case I_AM_GREP:
- X do_grep(argv+1);
- X break;
- X }
- X
- X nn_exit(0);
- X /*NOTREACHED*/
- X}
- X
- X/*
- X * nn_exit() --- called whenever a program exits.
- X */
- X
- Xnn_exit(n)
- X{
- X static int loop = 0;
- X
- X if (loop) exit(n);
- X loop++;
- X
- X visual_off();
- X
- X#ifdef NNTP
- X nntp_cleanup();
- X#endif /* NNTP */
- X close_master();
- X flush_newsrc();
- X
- X if (who_am_i == I_AM_NN)
- X log_usage();
- X
- X if (must_unlock)
- X proto_lock(I_AM_NN, PL_CLEAR);
- X
- X exit(n);
- X}
- END_OF_FILE
- if test 17064 -ne `wc -c <'nn.c'`; then
- echo shar: \"'nn.c'\" unpacked with wrong size!
- fi
- # end of 'nn.c'
- fi
- echo shar: End of archive 14 \(of 22\).
- cp /dev/null ark14isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 22 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
-
- exit 0 # Just in case...
-